﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Lucene.Linq.Utility;

namespace Lucene.Linq.Demo
{
    internal class Program
    {
        private static NorthwindIndexContext _index;
        
        private static void Main(string[] args)
        {
            const string path = @"C:\temp\index";
            //try
            //{
            //    Directory.Delete(path, true);
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine(ex);
            //}
            Directory.CreateDirectory(path);
            Console.WriteLine("Northwind Db index:{0}", path);

            _index = new NorthwindIndexContext(path, new NorthwindDataContext());

            // add all the customers/orders to the index
            //_index.Write(); // uncomment this line to write both Orders and Customers
            _index.Write<Customer>();

            // *** Uncomment any Demo below to view its output ***
            SimpleDemo(_index);
            //VariableDemo(_index);
            //ProjectionDemo(_index);
            //OrDemo(_index);
            //AndDemo(_index);
            //GroupDemo(_index);
            //DefaultFieldsDemo(_index);
            //WildCardDemo(_index);
            //SingleTermPrefixDemo(_index);
            //MultiTermPrefixDemo(_index);
            //FuzzyDemo(_index);
            //ProximityDemo(_index);
            //ExclusiveRangeDemo(_index);
            //InclusiveRangeDemo(_index);
            //RequireTermDemo(_index);
            //BoostTermDemo(_index);
            //NativeSyntaxDemo(_index);

            //todo: Make nested demo work
            //NestedDemo(_index);
            //todo: Make joind demo work
            //JoinDemo(_index);
            
            _index.Dispose();

            Console.WriteLine("Press any key to continue...");
            Console.ReadLine();
        }

        private static void SimpleDemo(NorthwindIndexContext index)
        {
            IQueryable<Customer> query = from c in index.Customers
                                         where c.ContactTitle == "Owner"
                                         select c;

            Console.WriteLine("Simple Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();

            List<Customer> results = query.ToList();
            Console.WriteLine("SimpleDemo returned {0} results", results.Count);
        }

        private static void VariableDemo(NorthwindIndexContext index)
        {
            const string name = "Maria";
            IQueryable<Customer> query = from c in index.Customers
                                         where c.ContactName == name
                                         select c;

            Console.WriteLine("Variable Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void ProjectionDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName == "maria"
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Projection Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void OrDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where (c.ContactName == "maria") || (c.CompanyName == "Ernst Handel")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Or Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void AndDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where (c.ContactName == "maria") && (c.CompanyName == "Alfreds Futterkiste")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("And Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void GroupDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where
                            (c.ContactName == "maria") ||
                            (c.ContactName == "Aria Cruz" && c.CompanyName == "Familia Arquibaldo")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Group Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void DefaultFieldsDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where (c.Match("Folies"))
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Default Fields Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void WildCardDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName == "ma?ia"
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Wildcard Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void SingleTermPrefixDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.StartsWith("mar")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Prefix Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void MultiTermPrefixDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.StartsWith("+Maria And")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Multi-Term Prefix Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void FuzzyDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Like("Maria")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Fuzzy Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine("Query Output: {0}", query.Count());
            Console.WriteLine();
        }

        private static void ProximityDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Like("Maria An", 1)
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Proximity Query:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void ExclusiveRangeDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Between("Annette", "Aria")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Exclusive Range Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void InclusiveRangeDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Include("Annette", "Aria")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Inlcusive Range Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void RequireTermDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Match("maria".Require(), "Anders")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Inlcusive Range Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void BoostTermDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName.Match("maria".Boost(3), "Art")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Inlcusive Range Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void NativeSyntaxDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.Search("((+la^4 OR en) OR (WeirdCustomName:mar* AND !CompanyName:Victuailles))")
                        select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

            Console.WriteLine("Native Syntax Range Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void NestedDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        where c.ContactName == "maria"
                        select new
                                   {
                                       Name = c.ContactName,
                                       Orders = from o in index.Orders
                                                where o.CustomerID == c.CustomerID
                                                select o
                                   };

            Console.WriteLine("Nested Demo:");

            foreach (var item in query)
            {
                Console.WriteLine(item.Name);
                foreach (Order order in item.Orders)
                {
                    Console.WriteLine("\tOrder:{0}", order.ShipAddress);
                }
            }

            //ObjectDumper.Write(query, 4);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }

        private static void JoinDemo(NorthwindIndexContext index)
        {
            var query = from c in index.Customers
                        from o in index.Orders
                        select new
                                   {
                                       Name = c.ContactName,
                                       Address = o.ShipAddress
                                   };

            Console.WriteLine("Join Demo:");
            ObjectDumper.Write(query);
            Console.WriteLine("Query Output: {0}", query);
            Console.WriteLine();
        }
    }
}